package com.bifrost.admin.controller;

import com.bifrost.annotation.CurrentAdmin;
import com.bifrost.constant.BonusPointsSource;
import com.bifrost.constant.BonusPointsUpdatedDetail;
import com.bifrost.entity.BonusPointsHistory;
import com.bifrost.entity.Customer;
import com.bifrost.entity.MerchantStore;
import com.bifrost.entity.User;
import com.bifrost.event.ClearBonusEvent;
import com.bifrost.excel.model.BondsInfo;
import com.bifrost.excel.model.CustomerInfo;
import com.bifrost.excel.model.CustomerStatisticsInfo;
import com.bifrost.exception.BonusPointsNotEnoughException;
import com.bifrost.model.ResultModel;
import com.bifrost.model.vo.PageVO;
import com.bifrost.repository.AdminUserRepository;
import com.bifrost.repository.BonusPointsHistoryRepository;
import com.bifrost.repository.CustomerRepository;
import com.bifrost.repository.CustomerTypeRepository;
import com.bifrost.repository.MerchantStoreRepository;
import com.bifrost.service.AdminUserService;
import com.bifrost.service.BonusPointsService;
import com.bifrost.service.CustomerInfoService;
import com.bifrost.service.CustomerService;
import com.bifrost.service.MerchantBonusService;
import com.bifrost.service.StoreService;
import com.bifrost.util.ExcelReportUtils;
import com.bifrost.util.NumberUtils;
import com.bifrost.util.QueryUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@RestController
@Api("门店会员积分相关接口")
@RequestMapping("/merchant/Bonus")
public class MerchantBonusController implements ApplicationContextAware {
    protected ApplicationContext applicationContext;
    @Autowired
    private BonusPointsHistoryRepository bonusPointsHistoryRepository;
    @Autowired
    private AdminUserRepository adminUserRepository;
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    BonusPointsService bonusPointsService;
    @Autowired
    CustomerService customerService;
    @Autowired
    private MerchantBonusService merchantBonusService;
    @Autowired
    private CustomerInfoService customerInfoService;
    @Autowired
    private MerchantStoreRepository merchantStoreRepository;
    @Autowired
    AdminUserService adminUserService;
    @Autowired
    CustomerTypeRepository customerTypeRepository;
    @Autowired
    StoreService storeService;

    @ApiOperation(value = "根据手机或会员卡号查询用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店号", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "phoneCard", value = "手机或会员卡号", required = true, dataType = "String", paramType = "query"),
    })
    @GetMapping("/getBonusInfo")
    public ResultModel getCustomerInfo(@CurrentAdmin Long userId,Long storeId, String phoneCard) {
        Map<String, Object> map = new HashMap<>();
        Customer customer;
        if (Pattern.matches("^1(\\d{10})$", phoneCard)) {
            customer = customerRepository.findCustomerByPhone(storeId, phoneCard);
        } else {
            customer = customerRepository.findCustomerByCard(storeId, phoneCard);
        }
        if (customer == null) {
            return ResultModel.error("没找到用户数据");
        }
        map.put("nickname", customer.getCustomerNickname());
        map.put("phone", customer.getCustomerPhone());
        map.put("carNumber", customer.getLoyaltyCard());
        map.put("bonus", customer.getBonusPoints());
        return ResultModel.ok().put("data", map);
    }

    @ApiOperation(value = "扣减积分")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店号", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "cardNumber", value = "会员卡号", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "decrementValue", value = "扣减积分", required = true, dataType = "BigInteger", paramType = "query"),
            @ApiImplicitParam(name = "remark", value = "备注", required = true, dataType = "String", paramType = "query"),
    })
    @GetMapping("/decrementBonus")
    public ResultModel decrementBonusPoints(@CurrentAdmin Long userId,Long storeId, String cardNumber, BigInteger decrementValue, String remark) throws BonusPointsNotEnoughException {

        User admin = adminUserRepository.getOne(userId);
        Customer customer = customerRepository.findCustomerByCard(storeId, cardNumber);
        if (customer == null) {
            return ResultModel.error("没找到用户数据");
        }
        if (decrementValue == null) {
            return ResultModel.error("积分有误");
        }
        //customerRepository.decrementBonusPoints(customer.getCustomerId(),decrementValue);
        BonusPointsSource source = BonusPointsSource.OFFLINE_STORE;
        BonusPointsUpdatedDetail detail = BonusPointsUpdatedDetail.BY_ADMINUSER;
        Long aLong = bonusPointsService.decrementBonusPoints(customer, "user"+NumberUtils.getRandomNumber(8), null, decrementValue, source, detail, remark,admin.getLastName());
        if (aLong != null) {
            bonusPointsHistoryRepository.updateOptNameById(admin.getDescription(),aLong);
            return ResultModel.ok("扣減积分成功");
        } else {
            return ResultModel.error("扣減积分失败");
        }
    }

    @ApiOperation(value = "增加积分积分")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店号", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "cardNumber", value = "会员卡号", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "incrementValue", value = "增加积分", required = true, dataType = "BigInteger", paramType = "query"),
            @ApiImplicitParam(name = "remark", value = "备注", required = true, dataType = "String", paramType = "query"),
    })
    @GetMapping("/incrementBonus")
    public ResultModel incrementBonusPoints(@CurrentAdmin Long userId,Long storeId,String cardNumber, BigInteger incrementValue, String remark) throws BonusPointsNotEnoughException {
        User admin = adminUserRepository.getOne(userId);
        Customer customer = customerRepository.findCustomerByCard(storeId, cardNumber);
        if (customer == null) {
            return ResultModel.error("没找到用户数据");
        }
        if (incrementValue == null) {
            return ResultModel.error("积分有误");
        }
        //customerRepository.incrementBonusPoints(customer.getCustomerId(),incrementValue);
        BonusPointsSource source = BonusPointsSource.OFFLINE_STORE;
        BonusPointsUpdatedDetail detail = BonusPointsUpdatedDetail.BY_ADMINUSER;
        Long aLong = bonusPointsService.incrementBonusPoints(customer, "user"+NumberUtils.getRandomNumber(8), incrementValue, source, detail, remark, customer.getBonusPoints().toString());
        if (aLong != null) {
            bonusPointsHistoryRepository.updateOptNameById(admin.getDescription(),aLong);
            return ResultModel.ok("增加积分成功");
        } else {
            return ResultModel.error("增加积分失败");
        }
    }

    @ApiOperation(value = "获取会员历史积分")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店号", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "cardNumber", value = "会员卡号", required = true, dataType = "String", paramType = "query"),
    })
    @GetMapping("/history")
    public ResultModel getHistoryBunds(@CurrentAdmin Long userId,Long storeId, String cardNumber) {

        User admin = adminUserRepository.getOne(userId);
        List<BonusPointsHistory> all = bonusPointsHistoryRepository.findAllByMerchantIdAndCardNumber(storeId, cardNumber);
        if (CollectionUtils.isNotEmpty(all)) {
            return ResultModel.ok().put("recordList", all);
        } else {
            return ResultModel.error("没有积分历史记录");
        }
    }

    //开始结束日期、会员卡号、手机号、日期、小票号
    @ApiOperation(value = "导出积分报表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "cardNumber", value = "会员卡号", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String", paramType = "query"),
    })
    @GetMapping("/exportBonus")
    public void exportBonus(@CurrentAdmin Long userId,Long[] merchantStoreIds,String startTime, String endTime, String cardNumber,String name, String phone, HttpServletResponse resp) {
        List<Long> storeIds = QueryUtils.getMerchantIds(adminUserRepository.getOne(userId),merchantStoreIds);
        List<BondsInfo> list = merchantBonusService.queryBonusReport(startTime, endTime, cardNumber,name, phone,storeIds);
        if (CollectionUtils.isNotEmpty(list)) {
            String title = "积分报表";
            ExcelReportUtils.exportExcel(list, title, title, BondsInfo.class, title + ".xls", resp);
        }
    }
    @GetMapping("/list")
    @ApiOperation("积分变更记录分页查询")
    public ResultModel list(Long[] merchantStoreIds,String startTime, String endTime, String name,String phone,@CurrentAdmin Long userId, String cardNum, @RequestParam(defaultValue = "1") Integer pageCode, @RequestParam(defaultValue = "10") Integer pageSize) {
        //List<Long> storeIds = getStoreIds(userId, merchantStoreIds);
        List<Long> storeIds = QueryUtils.getMerchantIds(adminUserRepository.getOne(userId),merchantStoreIds);
        PageVO pageVO = merchantBonusService.queryBonusReport(pageCode, pageSize, startTime, endTime, cardNum, name, phone, storeIds);
        return ResultModel.ok().put("pageVO", pageVO);
    }

    /*
    门店号、手机号、卡号、姓名、注册时间段
     */
    @ApiOperation(value = "导出会员基础信息表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "cardNumber", value = "会员卡号", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "customerName", value = "会员名称", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "registerDate", value = "注册时间段", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "bonus", value = "积分", required = false, dataType = "BigInteger", paramType = "query"),
            @ApiImplicitParam(name = "conditionType", value = "查询条件", required = false, dataType = "Integer", paramType = "query", defaultValue = "5"),
    })
    @GetMapping("/exportCustomer")
    public void exportCustomer(@CurrentAdmin Long userId,String phone,Long[] storeId, String cardNumber, String customerName, String sRegisterDate,String eRegisterDate, BigInteger bonus, Integer conditionType, HttpServletResponse resp) {
        String[] registerDate={sRegisterDate,eRegisterDate};
        List<Long> storeIds = QueryUtils.getMerchantIds(adminUserRepository.getOne(userId),storeId);
        List<CustomerInfo> list = customerInfoService.queryCustomerInfo(storeIds, phone, cardNumber, customerName, registerDate, bonus, conditionType);
        if (CollectionUtils.isNotEmpty(list)) {
            String title = "会员基础信息表";
            ExcelReportUtils.exportExcel(list, title, title, CustomerInfo.class, title + ".xls", resp);
        }
    }

    @ApiOperation(value = "查询会员基础信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "门店号", required = false, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "phone", value = "手机号", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "cardNumber", value = "会员卡号", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "customerName", value = "会员名称", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "registerDate", value = "注册时间段", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "bonus", value = "积分", required = false, dataType = "BigInteger", paramType = "query"),
            @ApiImplicitParam(name = "conditionType", value = "查询条件", required = false, dataType = "Integer", paramType = "query", defaultValue = "5"),
            @ApiImplicitParam(name = "page", value = "当前页", required = false, dataType = "Integer", paramType = "query", defaultValue = "1"),
            @ApiImplicitParam(name = "pageSize", value = "页面大小", required = false, dataType = "Integer", paramType = "query", defaultValue = "10"),
            @ApiImplicitParam(name = "isActive", value = "是否激活", required = false, dataType = "Boolean", paramType = "query"),
    })
    @GetMapping("/pageCustomer")
    public ResultModel pageCustomer(@CurrentAdmin Long userId,Long[] storeId, String phone, String cardNumber, String customerName, String sRegisterDate,String eRegisterDate, BigInteger bonus, Integer conditionType, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, Boolean isActive) {
        String[] registerDate ={sRegisterDate,eRegisterDate};
        List<Long> storeIds = QueryUtils.getMerchantIds(adminUserRepository.getOne(userId),storeId);
        PageVO pageVO = customerInfoService.pageCustomerInfo(storeIds, phone, cardNumber, customerName, registerDate, bonus, conditionType, page, pageSize, isActive);
        return ResultModel.ok().put("pageVO", pageVO);
    }

    @ApiOperation(value = "会员汇总表")
    @GetMapping("/exportCustomerStatistics")
    public void exportCustomerStatisticsInfo(HttpServletResponse resp) {
        List<CustomerStatisticsInfo> list = new ArrayList<>();
        Sort.Order order = new Sort.Order(Sort.Direction.ASC, "merchantId");
        Sort sort = new Sort(order);
        List<MerchantStore> stores = merchantStoreRepository.findAll(sort);
        int i = 0;
        List<Object[]> total = customerRepository.queryTotal();
        for(Object[] l:total){
            CustomerStatisticsInfo customerStatisticsInfo = new CustomerStatisticsInfo();
            BigInteger l0 = (BigInteger)l[0];
            BigDecimal l2 = (BigDecimal)l[2];
            BigInteger l1 = (BigInteger)l[1];
            MerchantStore merchantStore = merchantStoreRepository.findOne(l0.longValue());
            customerStatisticsInfo.setSerialNumber(String.valueOf(++ i));
            customerStatisticsInfo.setStoreCode(merchantStore.getExternalId());
            customerStatisticsInfo.setTotalBonus(l2.toBigInteger());
            customerStatisticsInfo.setTotalCustomers(l1.longValue());
            list.add(customerStatisticsInfo);
        }
        if (CollectionUtils.isNotEmpty(list)) {
            String title = "会员汇总表";
            ExcelReportUtils.exportExcel(list, title, title, CustomerStatisticsInfo.class, title + ".xls", resp);
        }
    }


    @GetMapping("/clear")
    public ResultModel clearAllCustomerBonus(@CurrentAdmin Long userId , @RequestParam Long storeId) {

        ClearBonusEvent clearBonusEvent = new ClearBonusEvent(storeId);
        applicationContext.publishEvent(clearBonusEvent);
        return ResultModel.ok("积分清零中----");
    }

    @ExceptionHandler(value = {com.bifrost.exception.BonusPointsNotEnoughException.class})
    public ResultModel bonusPointsNotEnoughExceptionHandler(Exception ex) {
        return ResultModel.error(ex.getMessage());
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }

    private List<Long> getStoreIds(Long userId,String merchantStoreIds){
        User user = adminUserRepository.getOne(userId);
        Set<MerchantStore> stores = user.getMerchantStores();
        if(CollectionUtils.isEmpty(stores)){
            log.info("当前用户没有关联门店");
            throw new RuntimeException("当前用户没有关联门店");
        }
        List<Long> list = stores.stream()
                .map(store->store.getMerchantId())
                .collect(Collectors.toList());
        if(merchantStoreIds!=null){
            String[]  sStores = merchantStoreIds.split(",");
            List<Long> storeIds = new ArrayList<>();
            for (String str:sStores){
                Long storeId = Long.valueOf(str);
                if(list.contains(storeId)){
                    storeIds.add(storeId);
                }
            }
            return storeIds;
        }else{
            return list;
        }
    }
    private Long getStoreId(Long userId){
        User user = adminUserRepository.getOne(userId);
        MerchantStore store = user.getMerchantStore();
        if(store==null){
            log.info("当前用户没有关联门店");
            throw new RuntimeException("当前用户没有关联门店");
        }
        return store.getMerchantId();
    }
}
